package com.danskin.wechat.util;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;

import org.apache.commons.fileupload.util.Streams;
import org.apache.commons.lang3.StringUtils;

public class WeXinQrCodeUtil {

	/**
	 * 根据微信服务器上生成的二维码地址生成带logo的二维码并上传到ftp服务器
	 * 
	 * @param wxQrCodeUrl
	 * @return
	 * @author makunsmac
	 */
	public static String getAddLogoQrCode(String wxQrCodeUrl, String realPath) {
		// 把微信服务器上的二维码下载到本地
		String localQrCodeUrl = downloadQrCode(wxQrCodeUrl);
		// 把logo加入到下载下来的二维码上并上传到ftp服务器，返回上传地址
		if (StringUtils.isBlank(localQrCodeUrl)) {
			return null;
		}
		WeXinQrCodeUtil weXinQrCodeUtil = new WeXinQrCodeUtil();
		return weXinQrCodeUtil.getLogoQRCode(localQrCodeUrl, realPath);
	}

	/**
	 * 把微信服务器上生成的二维码下载到本地
	 * 
	 * @param wxQrCodeUrl
	 * @return
	 * @author makunsmac
	 */
	public static String downloadQrCode(String wxQrCodeUrl) {
		// 生成二维码文件名称
		String qrCodeName = String.valueOf(System.currentTimeMillis());
		// 下载到本地二维码的临时目录
		String localQrCodeUrlTemp = System.getProperty("catalina.home") + File.separator + "danskin-temp/qrCode/";

		// 如果本地二维码的临时目录不存在，创建该临时目录
		File localQrCodeTemp = new File(localQrCodeUrlTemp);
		if (!localQrCodeTemp.exists()) {
			localQrCodeTemp.mkdirs();
		}

		try {
			// 把微信服务器二维码下载到本地并返回本地路径
			URL url = new URL(wxQrCodeUrl);
			InputStream in = url.openStream();
			File file = new File(localQrCodeUrlTemp + qrCodeName);
			FileOutputStream out = new FileOutputStream(file);
			Streams.copy(in, out, true);
			return localQrCodeUrlTemp + qrCodeName;
		} catch (MalformedURLException e) {
			LogUtil.error("=====微信服务器二维码下载异常：MalformedURLException", e);
		} catch (FileNotFoundException e) {
			LogUtil.error("=====微信服务器二维码下载异常：FileNotFoundException", e);
		} catch (IOException e) {
			LogUtil.error("=====微信服务器二维码下载异常：IOException", e);
		}
		return null;
	}

	/**
	 * 生成带logo的二维码图片
	 * 
	 * @param localQrCodeUrl
	 * @return
	 * @author makunsmac
	 */
	public String getLogoQRCode(String localQrCodeUrl, String realPath) {
		// 获取项目中的logo地址
		String logoUrl = realPath + "img/logo/logo.png";
		try {
			// 生成本地二维码的BufferedImage图片
			BufferedImage qrCodeBI = getQrCodeBufferedImage(localQrCodeUrl);
			// 给二维码图片添加Logo
			return addLogoToQRCode(qrCodeBI, new File(logoUrl), new LogoConfig(), localQrCodeUrl);
		} catch (Exception e) {
			LogUtil.error("======生成带logo的二维码图片异常", e);
		}
		return null;
	}

	/**
	 * 给二维码图片添加Logo
	 * 
	 * @param qrCodeBI
	 * @param logoFile
	 * @param logoConfig
	 * @return
	 * @author makunsmac
	 */
	public static String addLogoToQRCode(BufferedImage qrCodeBI, File logoFile, LogoConfig logoConfig, String localQrCodeUrl) {
		try {

			// 读取二维码图片，并构建绘图对象
			Graphics2D qrCodeGraphics = qrCodeBI.createGraphics();

			// 读取Logo图片
			BufferedImage logoBI = ImageIO.read(logoFile);

			// 设置logo的大小,本人设置为二维码图片的20%,因为过大会盖掉二维码
			int widthLogo = logoBI.getWidth(null) > qrCodeBI.getWidth() * 3 / 10 ? (qrCodeBI.getWidth() * 3 / 10)
					: logoBI.getWidth(null),
					heightLogo = logoBI.getHeight(null) > qrCodeBI.getHeight() * 3 / 10
							? (qrCodeBI.getHeight() * 3 / 10) : logoBI.getHeight(null);

			//logo放在中心
			int x = (qrCodeBI.getWidth() - widthLogo) / 2;
			int y = (qrCodeBI.getHeight() - heightLogo) / 2;

			// 开始绘制图片
			qrCodeGraphics.drawImage(logoBI, x, y, widthLogo, heightLogo, null);
			
			qrCodeGraphics.dispose();
			logoBI.flush();
			qrCodeBI.flush();
			
			localQrCodeUrl += ".png";

			File file = new File(localQrCodeUrl);

			FileOutputStream out = new FileOutputStream(file);
			ImageIO.write(qrCodeBI, "png", out);
			out.close();
			
			//上传二维码到ftp服务器并返回路径
			FTPHelper uploadQrCode = FTPHelper.getInstance();
			String ftpQrCodeUrl = uploadQrCode.uploadQrCode(localQrCodeUrl, "qrCode");
			return ftpQrCodeUrl;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 生成二维码bufferedImage图片
	 *
	 * @param content
	 *            编码内容
	 * @param barcodeFormat
	 *            编码类型
	 * @param width
	 *            图片宽度
	 * @param height
	 *            图片高度
	 * @param hints
	 *            设置参数
	 * @return
	 */
	public static BufferedImage getQrCodeBufferedImage(String qrCodeUrl) {
		BufferedImage image = null;
		BufferedImage bimg = null;
		try {
			Image src = ImageIO.read(new File(qrCodeUrl));
			
			bimg = (BufferedImage) src;
			
			int width = src.getWidth(null);
	        int height = src.getHeight(null);
	        
	        int[] pixels = new int[width * height];
	        for (int y = 0; y < height; y++) {
	            for (int x = 0; x < width; x++) {
	                if (bimg.getRGB(x, y) == -1) {
	                    pixels[y * width + x] = 0xffffffff;
	                }else if(bimg.getRGB(x, y) == 0){//这个else要加上去，否者保存的二维码全黑
	                    pixels[y * width + x] = 0xff000000;
	                } else {
	                	pixels[y * width + x] = bimg.getRGB(x, y);
	                }
	            }
	        }
	        
	        image = new BufferedImage(width, height,
	                BufferedImage.TYPE_INT_RGB);
	        image.getRaster().setDataElements(0, 0, width, height, pixels);
			
		} catch (IOException e) {
			LogUtil.error("======生成二维码bufferedImage图片异常", e);
		}
		return image;
	}
}

class LogoConfig {
	// logo默认边框颜色
	public static final Color DEFAULT_BORDERCOLOR = Color.WHITE;
	// logo默认边框宽度
	public static final int DEFAULT_BORDER = 2;
	// logo大小默认为照片的1/5
	public static final int DEFAULT_LOGOPART = 5;

	private final int border = DEFAULT_BORDER;
	private final Color borderColor;
	private final int logoPart;

	/**
	 * Creates a default config with on color {@link #BLACK} and off color
	 * {@link #WHITE}, generating normal black-on-white barcodes.
	 */
	public LogoConfig() {
		this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART);
	}

	public LogoConfig(Color borderColor, int logoPart) {
		this.borderColor = borderColor;
		this.logoPart = logoPart;
	}

	public Color getBorderColor() {
		return borderColor;
	}

	public int getBorder() {
		return border;
	}

	public int getLogoPart() {
		return logoPart;
	}
}
